//
//  DZMReadLongPressView.swift
//  DZMeBookRead
//
//  Created by dengzemiao on 2019/4/30.
//  Copyright © 2019年 DZM. All rights reserved.
//


/// Pan手势状态
enum DZMPanGesStatus:NSInteger {
    // 开始手势
    case begin
    // 变换中
    case changed
    // 结束手势
    case end
}

/// 监控阅读长按视图通知
func DZM_READ_NOTIFICATION_MONITOR(target:Any, action:Selector) {
    
    NotificationCenter.default.addObserver(target, selector: action, name: NSNotification.Name(DZM_READ_NOTIFICATION_LONG_PRESS_VIEW), object: nil)
}

/// 发送阅读长按视图通知
func DZM_READ_NOTIFICATION_PUSH(userInfo:[AnyHashable : Any]?) {
    
    NotificationCenter.default.post(name: NSNotification.Name(rawValue: DZM_READ_NOTIFICATION_LONG_PRESS_VIEW), object: nil, userInfo: userInfo)
}

/// 移除阅读长按视图通知
func DZM_READ_NOTIFICATION_REMOVE(target:Any) {
    
    NotificationCenter.default.removeObserver(target, name: NSNotification.Name(rawValue: DZM_READ_NOTIFICATION_LONG_PRESS_VIEW), object: nil)
}

/// 长按阅读视图通知 info 数据 key
let DZM_READ_KEY_LONG_PRESS_VIEW:String = "DZM_READ_KEY_LONG_PRESS_VIEW"

/// 长按阅读视图通知
let DZM_READ_NOTIFICATION_LONG_PRESS_VIEW:String = "DZM_READ_LONG_PRESS_VIEW_NOTIFICATION"

/// 光标拖拽触发范围
let DZM_READ_LONG_PRESS_CURSOR_VIEW_OFFSET:CGFloat = -30

import UIKit

class DZMReadLongPressView: DZMReadView, NoteMenuDelegate {
    
    /// 开启拖拽
    private(set) var isOpenDrag:Bool = false
    
    /// 选中区域
    private var selectRange:NSRange!
    
    /// 选中区域CGRect数组
    private var rects:[CGRect] = []
    
    /// 长按
    private var longGes:UILongPressGestureRecognizer?
    
    /// 单击
    private var tapGes:UITapGestureRecognizer?
    
    /// 左光标
    private var LCursorView:DZMReadLongPressCursorView!
    
    /// 右光标
    private var RCursorView:DZMReadLongPressCursorView!
    
    /// 触摸的光标是左还是右
    private var isCursorLorR:Bool = true
    
    /// 是否触摸到左右光标
    private var isTouchCursor:Bool = false
    
    /// 回调是否触摸到光标
    public var returnTouchCursorBlock:((_ isTouchcursor:Bool)->(Void))?
    
    /// 动画时间
    private var duration:TimeInterval = DZM_READ_AD_TIME
    
    /// 放大镜
    private var magnifierView:DZMMagnifierView?
    
    ///  全局虚线 Point 数组
    private var globalDottedLinePoints:[NoteLineRangeModel] = []
    
    /// user Note 虚线 Point 数组
    private var userDottedLinePoints:[NoteLineRangeModel] = []
    
    ///  userLines 自己画线的数组
    ///  包含 直线，虚线，底色
    private var userLineRanges:[NoteLineRangeModel] = []
    
    /// 笔记 点位合并 数组
    private var notePointMerges:[NoteLineItemModel] = []
    
    ///  菜单是否显示
    public  var menuShowState:Bool = false
        
    /// 拼音 rangesinfo
    private var pinyinRanges:[pinyinRangeModel] = []
    
    
    override init(frame: CGRect) {
        
        super.init(frame: frame)
        
        longGes = UILongPressGestureRecognizer(target: self, action: #selector(longAction(long:)))
        addGestureRecognizer(longGes!)
        
        tapGes = UITapGestureRecognizer(target: self, action: #selector(tapAction(tap:)))
        tapGes!.isEnabled = false
        addGestureRecognizer(tapGes!)
        
        
    }
    
    //MARK: == setup 划线数据
    var noteLinesModel: NoteLinesModel! {
        didSet {
            updateNoteLines()
        }
    }
    
    //MARK: == 拼音range 换算
    func setupPinyinRanges(pinyinContent:String){
        pinyinRanges.removeAll()
        
        let strContent:NSString = pinyinContent as NSString
        
        for i in 0..<strContent.length {
            
          let c =  strContent.substring(with: NSRange(location: i, length: 1))
            YLLog("index=\(i),value=\(c),code=\(c.unicodeScalars.map{$0.value})")
            if c.unicodeScalars.map({$0.value}).last == 65533, (pinyinRanges.first(where: {$0.start == i || $0.start + 1 == i}) == nil) {
               let pinyin = pinyinRangeModel()
                pinyin.start = i
                pinyin.end = i + 2
                pinyin.originalIndex = pinyin.end - ((pinyinRanges.count + 1) * 2)
                pinyinRanges.append(pinyin)
            }
        }
        
    }
    
    /// 获取拼音换算后的range
    private func getPinyinCharacterRange(start:Int,end:Int) -> NSRange{
        var tempRange:NSRange = NSRange()
        var newStart:Int = start
        var newEnd:Int = end
        
        var isFirstStart:Bool = false
        
        var isinRange:Bool = false
        
        for (i,item) in pinyinRanges.enumerated() {
            if item.originalIndex >= start && item.originalIndex <= end {
                isinRange = true
                if item.originalIndex == start {
                    if isFirstStart == false{
                        newStart = item.start
                    }
                    isFirstStart = true
                    newEnd = end + item.range.length
                    
                }else{
                    if isFirstStart == false {
                        newStart = start + (i * 2)
                    }
                    isFirstStart = true
                    
                    newEnd = end + ((i + 1) * 2)
                    
                }
            }else{
                
                if  item.originalIndex > start && isinRange == false {

                    let tempStart = start + (i * 2)
                    let tempEnd = end + (i * 2)
               
                    return NSRange(location: tempStart, length: tempEnd - tempStart)
                }
                
                if item.originalIndex < start && isinRange == false{
                    newStart = start + ((i + 1) * 2)
                    newEnd = end + ((i + 1) * 2)
                }
                
            }
        }
        
        tempRange = NSRange(location: newStart, length: newEnd - newStart)
        
        return tempRange
    }

    /// 获取 正常range
    private func getOriginalRange(pyRange:NSRange) -> NSRange{
        let rangeStart: Int = pyRange.location
        let rangeEnd: Int = pyRange.location + pyRange.length
        
        var tempRange:NSRange = NSRange()
        var inRangeStart: Int = rangeStart
        var inRangeEnd: Int = rangeEnd
        
        var isinRange:Bool = false
        
        var isFirstStart:Bool = false
        
        for (i,item) in pinyinRanges.enumerated() {
            if item.start >= rangeStart &&  item.end <= rangeEnd {
                isinRange = true
                if item.start == rangeStart {
                    if isFirstStart == false{
                        inRangeStart = item.originalIndex
                    }
                    isFirstStart = true
                    inRangeEnd = rangeEnd - ((i + 1) * 2)
                }else{
                    if isFirstStart == false {
                        inRangeStart = rangeStart - (i * 2)
                    }
                    isFirstStart = true
                    
                    inRangeEnd = rangeEnd - ((i + 1) * 2)
                }
            }else {
                
                
                if  item.start >= rangeEnd && isinRange == false {
                    let tempStart = rangeStart - (i  * 2)
                    let tempEnd = rangeEnd - (i  * 2)
                    
                    return NSRange(location: tempStart, length: tempEnd - tempStart)
                    
                }
            }
        }
        
        tempRange = NSRange(location: inRangeStart, length: inRangeEnd - inRangeStart)
        
        return tempRange
    }
    
    public func updateNoteLines(){
        guard noteLinesModel != nil else {
            return
        }
    
        
        //全局 笔记虚线
        globalDottedLinePoints.removeAll()
        let goballines = noteLinesModel.gobal_note_lines
        if  goballines.count > 0 {
            var gobalRects:[CGRect] = []
            for line in goballines {
                var tempRange:NSRange = NSRange(location: line.s, length: line.length)
                if pageModel.isPinyin{
                    tempRange = getPinyinCharacterRange(start: line.s, end: line.e)
                }
                
                gobalRects.append(contentsOf: DZMCoreText.GetRangeRects(range: tempRange, frameRef: frameRef, content: pageModel.content.string))
            }
            globalDottedLinePoints.append(contentsOf: getDottedLinePoints(selectRects: gobalRects))
        }
        
        if noteLinesModel.user_note_lines.count > 0 {
            setupUserDottedRanges(userDotteds: noteLinesModel.user_note_lines)
        }
        
        if noteLinesModel.user_lines.count > 0{
            setupUserLineRanges(userLines: noteLinesModel.user_lines)
        }
        
        notePointMergeSort(globalNoteLines: noteLinesModel.gobal_note_lines, userNotelines: noteLinesModel.user_note_lines)
        
        setNeedsDisplay()
    }
    
    public func setupUserDottedRanges(userDotteds:[NoteLineItemModel]){
        //自己的笔记虚线
        userDottedLinePoints.removeAll()
        
        if  userDotteds.count > 0 {
            var userRects:[CGRect] = []
            for line in userDotteds {
                
                var tempRange:NSRange = NSRange(location: line.s, length: line.length)
                if pageModel.isPinyin{
                    tempRange = getPinyinCharacterRange(start: line.s, end: line.e)
                }
                
                userRects.append(contentsOf: DZMCoreText.GetRangeRects(range: tempRange, frameRef: frameRef, content: pageModel.content.string))
            }
            userDottedLinePoints.append(contentsOf: getDottedLinePoints(selectRects: userRects))
            
        }
        
    }

    //MARK: ==自己 画线（虚 直 波浪）
    public func setupUserLineRanges(userLines:[NoteLineItemModel]){
        userLineRanges.removeAll()
        
        if  userLines.count > 0 {
            
            for line in userLines {
                var tempRange:NSRange = NSRange(location: line.s, length: line.length)
                if pageModel.isPinyin{
                    tempRange = getPinyinCharacterRange(start: line.s, end: line.e)
                }
                
                let LineRects:[CGRect] = DZMCoreText.GetRangeRects(range: tempRange, frameRef: frameRef, content: pageModel.content.string)
                
                for rect in LineRects{
                    let rangeModle = NoteLineRangeModel()
                    rangeModle.lineType = NoetMenuType.init(rawValue: line.l)!
                    rangeModle.rect = rect
                    rangeModle.startPoint = CGPoint(x: rect.minX, y: rect.minY)
                    rangeModle.endPoint = CGPoint(x: rect.maxX, y: rect.minY)
                    
                    userLineRanges.append(rangeModle)
                }
                
            }
            
        }
    }
    
    //MARK: == 笔记点位合并 排序
    private func notePointMergeSort(globalNoteLines:[NoteLineItemModel], userNotelines:[NoteLineItemModel]){
        
        DispatchQueue.global().async {
            
            var tempMergeArray:[NoteLineItemModel] = []
            if  globalNoteLines.count <= 0 {
                tempMergeArray = userNotelines
            }
            if userNotelines.count <= 0 {
                tempMergeArray = globalNoteLines
            }
           
            
            if tempMergeArray.count <= 0 {
                
                var tempSortArray:[NoteLineItemModel] = []
                
                tempSortArray.append(contentsOf: globalNoteLines)
                tempSortArray.append(contentsOf: userNotelines)
                
                tempSortArray.sort { item1, item2 in
                    return item1.s < item2.s
                }
                YLLog("sortArray:\(tempSortArray)")
                
               
                var newStart = -1
                var newEnd = -1
                for (i,item) in tempSortArray.enumerated(){
                    let nextIndex = i + 1
                    
                    if i == 0 {
                        newStart = item.s
                        newEnd  = item.e
                    }
                    
                    if (tempSortArray.count - 1) >= nextIndex{
                        let nextPoint = tempSortArray[nextIndex]
                        
                        if nextPoint.s < newEnd {
                            
                            if nextPoint.e > newEnd {
                                newEnd = nextPoint.e
                            }
                            
                        }else{
                            let tempPoint = NoteLineItemModel()
                            tempPoint.s = newStart
                            tempPoint.e = newEnd
                            
                            tempMergeArray.append(tempPoint)
                            newStart = nextPoint.s
                            newEnd = nextPoint.e
                        }
                        
                    }else {
                        let tempPoint = NoteLineItemModel()
                        tempPoint.s = newStart
                        tempPoint.e = newEnd
                        tempMergeArray.append(tempPoint)
                        
                    }
                    
                }
                
                
            }
            
            guard tempMergeArray.count > 0 else {
                  return
            }
            self.notePointMerges.removeAll()
            self.notePointMerges.append(contentsOf: tempMergeArray)
          
           
        }
    }
    
    // 点击的区域
    func tapPointInNoteLineRange(tapRange:NSRange) ->NoteLineItemModel?{
        var lineModel:NoteLineItemModel?
        
        if self.notePointMerges.count > 0 {
            
            let index = searchTargetIndex(self.notePointMerges, tapRange)
            if index >= 0 {
                lineModel = self.notePointMerges[index]
            }
        }
        
        return lineModel
    }
    
    //MARK: == 根据 range 判断是否已经画线
    private func selectRangeIsLine(user_lines:[NoteLineItemModel],range:NSRange) ->Bool{
        
        var begin = 0 , end = user_lines.count - 1
        while begin <= end {
            //取中间下标
            let mid = begin + (end - begin) / 2
            
            
            if user_lines[mid].s <= range.location && user_lines[mid].e >= range.length + range.location{
                return true
            }
            
            // 如果中间下标小于查找目标值，那么左指针右移 扩大搜索面积
            if user_lines[mid].s < range.location {
                begin = mid + 1
            }
            
            // 如果中间下标大于查找目标值，那么右指针左移 缩小搜索面积
             if user_lines[mid].s > range.location {
                end = mid - 1
                 
             }
             
            if mid == 0 {
                if user_lines[mid].s <= range.location && user_lines[mid].e >= range.length + range.location {
                    return true
                }else {
                    return false
                }
            }
            
            }

        return false
    }
    
    func searchTargetIndex(_ nums:[NoteLineItemModel] ,  _ target:NSRange) -> Int {
        
        // 二分查找的基础 建立在数组为有序数组上，也就是说数组内的数据要从小到大排列
        
        // 定义双指针，begin为0左边下标， end 最后一个下标
        var begin = 0 , end = nums.count - 1
        while begin <= end {
            //取中间下标
            let mid = begin + (end - begin) / 2
            // 如果中间下标小于查找目标值，那么左指针右移 扩大搜索面积
            if nums[mid].e < target.location {
                begin = mid + 1
            }
            // 如果中间下标大于查找目标值，那么右指针左移 缩小搜索面积
            else if nums[mid].e > target.location &&  nums[mid].s > target.location{
                end = mid - 1
            }
            else{
               return mid
            }
        }
        
        return -1
    }
    
    /// 创建放大镜
     func creatMagnifierView(windowPoint: CGPoint) {
        
        if magnifierView == nil {
            
            magnifierView = DZMMagnifierView()
            magnifierView?.backgroundColor = UIColor.red
            magnifierView?.targetWindow = window
            magnifierView?.targetPoint = windowPoint
        }
    }
    
    // MARK: 手势事件
    
    /// 单击事件 ，可实现点击画线部分查看笔记
    @objc private func tapAction(tap:UITapGestureRecognizer) {
        
        // 重置页面数据
        reset()
        /*
        // 触摸位置 画线部分的文字
        let point = tap.location(in: self)
        let range = DZMCoreText.GetTouchLocationRange(point: point, frameRef: frameRef)
        
        var parameRange:NSRange = range
        var content:String = pageModel.content.string
        if pageModel.isPinyin {
           parameRange = getOriginalRange(pyRange: range)
            content = pageModel.pureContent
        }
        
        if let lineModel = tapPointInNoteLineRange(tapRange: parameRange) {
            
            let rangeStr =  content.substring(NSRange(location: lineModel.s, length: lineModel.length))
            let lineRange = NSRange(location: lineModel.s, length: lineModel.length)
            
            YLLog("笔记：\(rangeStr)")
            
        }
        */
        
    }
    
    /// 长按事件
    @objc private func longAction(long:UILongPressGestureRecognizer) {
        
        // 触摸位置
        let point = long.location(in: self)
        
        // 触摸位置
        let windowPoint = long.location(in: window)
        
        // 触摸开始 触摸中
        if long.state == .began {
            
            // 发送通知
            DZM_READ_NOTIFICATION_PUSH(userInfo: [DZM_READ_KEY_LONG_PRESS_VIEW : NSNumber(value: true)])
            
            // 放大镜
            creatMagnifierView(windowPoint: windowPoint)
            
        }else if long.state == .changed {
            
            // 设置放大镜位置
            magnifierView?.targetPoint = windowPoint
            
        }else{ // 触摸结束
            
            // 获得选中区域
            //            selectRange = DZMCoreText.GetTouchLineRange(point: point, frameRef: frameRef)
            selectRange = DZMCoreText.GetTouchLocationRange(point: point, frameRef: frameRef)
            
            
            // 获得选中选中范围
            rects = DZMCoreText.GetRangeRects(range: selectRange!, frameRef: frameRef, content: pageModel.content.string)
            
            // 显示光标
            cursor(isShow: true)
            
            // 设置放大镜位置
            magnifierView?.targetPoint = windowPoint
            
            // 移除
            magnifierView?.remove({ [weak self] () in
                
                // 清空
                self?.magnifierView = nil
                
                // 显示菜单
                self?.showMenu(isShow: true)
            })
            
            // 重绘
            setNeedsDisplay()
            
            // 开启手势
            if !rects.isEmpty {
                
                // 手势状态
                longGes?.isEnabled = false
                tapGes?.isEnabled = true
                isOpenDrag = true
                
                // 发送通知
                DZM_READ_NOTIFICATION_PUSH(userInfo: [DZM_READ_KEY_LONG_PRESS_VIEW : NSNumber(value: false)])
            }
        }
    }
    
    // MARK: 页面触摸拖拽处理
    
    /// 触摸开始
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        
        drag(touches: touches, status: .begin)
    }
    
    /// 触摸移动
    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        
        drag(touches: touches, status: .changed)
    }
    
    /// 触摸结束
    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        
        drag(touches: touches, status: .end)
    }
    
    /// 触摸取消
    override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
        
        drag(touches: touches, status: .end)
    }
    
    /// 解析触摸事件
    private func drag(touches: Set<UITouch>, status: DZMPanGesStatus) {
        
        if isOpenDrag {
            
            let touch:UITouch? = ((touches as NSSet).anyObject() as? UITouch)
            
            let point = touch?.location(in: self)
            
            let windowPoint = touch?.location(in: self.window)
            
            drag(status: status, point: point!, windowPoint: windowPoint!)
        }
    }
    
    /// 拖拽事件解析
    func drag(status:DZMPanGesStatus, point:CGPoint, windowPoint:CGPoint) {
        
        // 检查是否超出范围
        let point = CGPoint(x: min(max(point.x, 0), pageModel.contentSize.width), y: min(max(point.y, 0), pageModel.contentSize.height))
        
        // 触摸开始
        if status == .begin {
            
            // 隐藏菜单
            showMenu(isShow: false)
            
            if LCursorView.frame.insetBy(dx: DZM_READ_LONG_PRESS_CURSOR_VIEW_OFFSET, dy: DZM_READ_LONG_PRESS_CURSOR_VIEW_OFFSET).contains(point) { // 触摸到左边光标
                
                isCursorLorR = true
                
                isTouchCursor = true
                
            }else if RCursorView.frame.insetBy(dx: DZM_READ_LONG_PRESS_CURSOR_VIEW_OFFSET, dy: DZM_READ_LONG_PRESS_CURSOR_VIEW_OFFSET).contains(point) { // 触摸到右边光标
                
                isCursorLorR = false
                
                isTouchCursor = true
                
            }else{ // 没有触摸到光标
                
                isTouchCursor = false
            }
            
            // 触摸到了光标
            if isTouchCursor {
                
                // 放大镜
                creatMagnifierView(windowPoint: windowPoint)
            }
            
        }else if status == .changed { // 触摸中
            
            // 触摸到光标
            if isTouchCursor {
                
                // 设置放大镜位置
                magnifierView?.targetPoint = windowPoint
            }
            
            // 判断触摸
            if isTouchCursor && selectRange != nil {
                
                // 触摸到的位置
                let location = DZMCoreText.GetTouchLocation(point: point, frameRef: frameRef)
                
                // 无结果
                if location == -1 {
                    return
                    
                }
                
                // 刷新选中区域
                updateSelectRange(location: location)
                
                // 获得选中选中范围
                rects = DZMCoreText.GetRangeRects(range: selectRange, frameRef: frameRef, content: pageModel.content.string)
                
                // 更新光标位置
                updateCursorFrame()
            }
            
        }else{ // 触摸结束
            
            // 触摸到光标
            if isTouchCursor {
                
                // 设置放大镜位置
                magnifierView?.targetPoint = windowPoint
                
                // 移除
                magnifierView?.remove({ [weak self] () in
                    
                    // 清空
                    self?.magnifierView = nil
                    
                    // 显示菜单
                    self?.showMenu(isShow: true)
                })
                
            }else{
                
                // 显示菜单
                
                if selectRange != nil {
                    showMenu(isShow: true)
                }
                
            }
            
            // 结束触摸
            isTouchCursor = false
        }
        
        if returnTouchCursorBlock != nil {
            returnTouchCursorBlock!(isTouchCursor)
        }
        
        // 重绘
        setNeedsDisplay()
    }
    
    /// 刷新选中区域
    private func updateSelectRange(location:Int) {
        
        // 左右 Location 位置
        let LLocation = selectRange!.location
        let RLocation = selectRange!.location + selectRange!.length
        
        // 判断触摸
        if isCursorLorR { // 左边
            
            if location < RLocation {
                
                if location > LLocation {
                    
                    selectRange!.length -= location - LLocation
                    
                    selectRange!.location = location
                    
                }else if location < LLocation {
                    
                    selectRange!.length += LLocation - location
                    
                    selectRange!.location = location
                }
                
            }else{
                
                isCursorLorR = false
                
                var length = location - RLocation
                
                let tempLength = (length == 0 ? 1 : 0)
                
                length = (length == 0 ? 1 : length)
                
                selectRange?.length = length
                
                selectRange?.location = RLocation - tempLength
                
                updateSelectRange(location: location)
            }
            
        }else{ // 右边
            
            if location > LLocation {
                
                if location > RLocation {
                    
                    selectRange!.length += location - RLocation
                    
                }else if location < RLocation {
                    
                    selectRange!.length -= RLocation - location
                }
                
            }else{
                
                isCursorLorR = true
                
                let tempLength = LLocation - location
                
                let length = (tempLength == 0 ? 1 : tempLength)
                
                selectRange?.length = length
                
                selectRange?.location = LLocation - tempLength
                
                updateSelectRange(location: location)
            }
        }
    }
    
    // MARK: 光标处理
    
    /// 隐藏或显示光标
    private func cursor(isShow:Bool) {
        
        if isShow {
            
            if !rects.isEmpty && LCursorView == nil {
                
                LCursorView = DZMReadLongPressCursorView()
                LCursorView.isTorB = true
                addSubview(LCursorView)
                
                RCursorView = DZMReadLongPressCursorView()
                RCursorView.isTorB = false
                addSubview(RCursorView)
                
                updateCursorFrame()
            }
            
        }else{
            
            if LCursorView != nil {
                
                LCursorView.removeFromSuperview()
                LCursorView = nil
                
                RCursorView.removeFromSuperview()
                RCursorView = nil
            }
        }
    }
    
    /// 更新光标位置
    private func updateCursorFrame() {
        
        if !rects.isEmpty && LCursorView != nil {
            
            let cursorViewW:CGFloat = 10
            let cursorViewSpaceW:CGFloat = cursorViewW / 4
            let cursorViewSpaceH:CGFloat = cursorViewW / 1.1
            let first = rects.first!
            let last = rects.last!
            
            LCursorView.frame = CGRect(x: first.minX - cursorViewW + cursorViewSpaceW, y: bounds.height - first.minY - first.height - cursorViewSpaceH, width: cursorViewW, height: first.height + cursorViewSpaceH)
            
            RCursorView.frame = CGRect(x: last.maxX - cursorViewSpaceW, y: bounds.height - last.minY - last.height, width: cursorViewW, height: last.height + cursorViewSpaceH)
        }
    }
    
    // MARK: 重置页面
    
    /// 重置页面数据
    func reset() {
        
        // 发送通知
        DZM_READ_NOTIFICATION_PUSH(userInfo: [DZM_READ_KEY_LONG_PRESS_VIEW : NSNumber(value: true)])
        
        // 手势状态
        tapGes?.isEnabled = false
        isOpenDrag = false
        longGes?.isEnabled = true
        
        // 移除菜单
        showMenu(isShow: false)
        
        // 清空选中
        selectRange = nil
        rects.removeAll()
        
        // 移除光标
        cursor(isShow: false)
        
        // (如果有放大镜)移除放大镜
        magnifierView?.remove({ [weak self] () in
            
            // 清空
            self?.magnifierView = nil
        })
        
        // 重绘
        setNeedsDisplay()
    }
    
    // MARK: 菜单相关
    
    /// 隐藏或显示菜单
    private func showMenu(isShow:Bool) {
        menuShowState = isShow
        if isShow { // 显示
            
            if !rects.isEmpty {
                
                let rect = DZMCoreText.GetMenuRect(rects: rects, viewFrame: bounds)
                
                let startWindowRect = self.convert(rect, to: self.getCurrentVC?.view)
                
                let centerX = (startWindowRect.minX + rect.width) / 2
                
                let centerRect = CGRect(x: centerX, y: startWindowRect.minY , width: rect.width, height: rect.height)
                
                
                DelayHandle {
                    
                    let index = self.searchTargetIndex(self.noteLinesModel.user_lines, self.selectRange)
                    
                    var userLine = NoteLineItemModel()
                    if index >= 0 {
                        userLine = self.noteLinesModel.user_lines[index]
                    }
                    
                    self.noteMenu.showMenuWithRect(rect: centerRect,isLined: index >= 0,linetype: NoetMenuType.init(rawValue: userLine.l)!)
                }
            }
            
        }else{ // 隐藏
            noteMenu.hiddenMenu()
        }
    }
    
    /// 允许菜单事件
    /*
     override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
     
     if action == #selector(clickCopy) { return true }
     
     return false
     }
     */
    
    /// 允许成为响应者
    override var canBecomeFirstResponder: Bool {
        
        return true
    }
    
    /// 复制事件
    @objc private func clickCopy() {
        
        if selectRange != nil {
            
            let temSelectRange = selectRange!
            
            let tempContent = pageModel.content
            
            DispatchQueue.global().async {
                UIPasteboard.general.string = tempContent?.string.substring(temSelectRange)
                
                
                DispatchQueue.main.async {
                   
                }
                
            }
            
            // 重置页面数据
            reset()
        }
    }
    
    //MARK: -----------------------Network----------------------------
    /// 新增画线, 上传坐标给后台，后台返回合并后的线段，重绘
    private func AddPoetryLine(range:NSRange,lineType:Int){
        
        let lineModel = NoteLineItemModel()
        lineModel.s = range.location
        lineModel.e = range.location + range.length
        lineModel.l = lineType
        
        self.noteLinesModel.user_lines.append(lineModel)
        
        self.setupUserLineRanges(userLines: self.noteLinesModel.user_lines)
        
        self.setNeedsDisplay()
        
    }
    
    /// 删除划线
    private func deletePoetryLine(range:NSRange){
          
    }
    
    // MARK: 绘制 draw
    override func draw(_ rect: CGRect) {
        
        if (frameRef == nil) {return}
        
        let ctx = UIGraphicsGetCurrentContext()
        
        ctx?.textMatrix = CGAffineTransform.identity
        
        ctx?.translateBy(x: 0, y: bounds.size.height)
        
        ctx?.scaleBy(x: 1.0, y: -1.0)
        
        
        
        // 绘制全局虚线
        if globalDottedLinePoints.count > 0 {
            for linePoint in globalDottedLinePoints {
                Note_Text_GlobalDotted_Color_8F8F8F.setStroke()
                ctx?.setLineWidth(scaleHeight(1))
                ctx?.move(to: linePoint.startPoint)
                ctx?.addLine(to: linePoint.endPoint)
                ctx?.setLineDash(phase: 0, lengths: [2,2])
                ctx?.strokePath()
            }
            ctx?.setLineDash(phase: 0, lengths: [])
        }
        
        // 绘制 user 虚线
        if userDottedLinePoints.count > 0 {
            for linePoint in userDottedLinePoints {
                Note_Text_Line_COLOR_F04848.setStroke()
                ctx?.setLineWidth(scaleHeight(1))
                ctx?.move(to: linePoint.startPoint)
                ctx?.addLine(to: linePoint.endPoint)
                ctx?.setLineDash(phase: 0, lengths: [2,2])
                ctx?.strokePath()
            }
            ctx?.setLineDash(phase: 0, lengths: [])
        }
        
        // 直线、波浪线、底色
        if userLineRanges.count > 0 {
            for userLine in userLineRanges {
                //直线
                if userLine.lineType == .solid_line {
                    Note_Text_Line_COLOR_F04848.setStroke()
                    ctx?.setLineWidth(scaleHeight(1))
                    ctx?.move(to: userLine.startPoint)
                    ctx?.addLine(to: userLine.endPoint)
                    ctx?.strokePath()
                }
                
                // 波浪线
                if userLine.lineType == .wave_line {
                    Note_Range_COLOR_White.setStroke()
                    ctx?.setLineWidth(scaleHeight(1.5))
                    ctx?.move(to: userLine.startPoint)
                    ctx?.addLine(to: userLine.endPoint)
                    ctx?.strokePath()
                    
                    
                    Note_Text_WaveLine_COLOR_F0C348.setStroke()
                    
                    let startPoint = userLine.startPoint
                    let endPoint = userLine.endPoint
                    
                    ctx?.setLineWidth(scaleHeight(1))
                    ctx?.move(to: startPoint)
                    
                    for x in Int(startPoint.x)...Int(endPoint.x) {
                        //标准正玄波浪公式
                        WAVE_Line_Y = 2 * sin(2 * .pi * CGFloat(x) / WAVE_Line_W) + WAVE_Line_Height / 2
                        let point = CGPoint(x: Double(x), y: Double(startPoint.y - WAVE_Line_Y))
                        ctx?.addLine(to: point)
                    }
                    ctx?.strokePath()
                    
                    
                }
                
                // 底色
                if userLine.lineType == .bg_color {
                    let path = CGMutablePath()
                    
                    Note_Text_bgColor_FAE3BA.setFill()
                    
                    path.addRect(userLine.rect)
                    
                    ctx?.addPath(path)
                    ctx?.fillPath()
                    
                    Note_Range_COLOR_White.setStroke()
                    ctx?.setLineWidth(scaleHeight(1.5))
                    ctx?.move(to: userLine.startPoint)
                    ctx?.addLine(to: userLine.endPoint)
                    ctx?.strokePath()
                    
                }
                
            }
            
        }
        
        //选择区域
        if selectRange != nil && !rects.isEmpty {
            
            let path = CGMutablePath()
            
            Note_Range_COLOR_C1DCF7.setFill()
            
            path.addRects(rects)
            
            ctx?.addPath(path)
            
            ctx?.fillPath()
        }
        
        CTFrameDraw(frameRef!, ctx!)
        
    }
    
    
    //MARK: == lazy
    
    lazy var noteMenu: NoteMenuController = {
        let menu = NoteMenuController()
        menu.bgMenuTapBlock = {[weak self] in
            self?.reset()
        }
        menu.isHidden = true
        menu.delegate = self
        
        if getKeyWindow() != nil{
            getKeyWindow()?.addSubview(menu)
        }else{
            self.getCurrentVC?.view.addSubview(menu)
        }
        
        
        
        menu.snp.makeConstraints { make in
            make.size.equalTo(CGSize(width: kScreenWidth - 50 , height: NoteMenuController.menuSuperHeight))
            make.centerX.equalToSuperview()
            make.top.equalToSuperview()
        }
        
        return menu
    }()
    

    
    /// 释放
    deinit {
        
        tapGes?.removeTarget(self, action: #selector(tapAction(tap:)))
        tapGes = nil
        
        longGes?.removeTarget(self, action: #selector(longAction(long:)))
        longGes = nil
    }
    
    required init?(coder aDecoder: NSCoder) {
        
        fatalError("init(coder:) has not been implemented")
    }
}

extension DZMReadLongPressView {
    
    func noteMenu(menuControl: NoteMenuController, didSelectItem type: NoetMenuType) {
        switch type {
        case .bg_color:
            YLLog("底色")
            guard selectRange != nil else {
                reset()
                return
            }
            
            AddPoetryLine(range: selectRange, lineType: type.rawValue)
            reset()
        case .solid_line:
            YLLog("直线")
            guard selectRange != nil else {
                reset()
                return
            }
            
            AddPoetryLine(range: selectRange, lineType: type.rawValue)
            
            reset()
        case .wave_line:
            YLLog("波浪线")
            guard selectRange != nil else {
                reset()
                return
            }
            
            AddPoetryLine(range: selectRange, lineType: type.rawValue)
            
            reset()
        case .deLine:
            //删除线
            YLLog("删除线")
            if selectRange != nil {
                deletePoetryLine(range: selectRange)
            }
            reset()
        case .copy:
            clickCopy()
            
        case .write:
            YLLog("笔记")
            guard selectRange != nil else {
                return
            }
            
            var rangeText = pageModel.content.string.substring(selectRange)
            
            if pageModel.isPinyin {
               let tempRange = getOriginalRange(pyRange: selectRange)
                rangeText = pageModel.pureContent.substring(tempRange)
            }
         
        case .errata:
 
            guard selectRange != nil else {
                return
            }
            
            var rangeText = pageModel.content.string.substring(selectRange)
            

            reset()
            
        default:
            YLLog("other")
        }
    }
    
    //MARK: == set 虚线
    // 虚线数组
    func getDottedLinePoints(selectRects:[CGRect]) ->[NoteLineRangeModel]{
        var linePoints:[NoteLineRangeModel] = []
        
        for item in selectRects{
            let rangeModel = NoteLineRangeModel()
            rangeModel.startPoint =  CGPoint(x: item.minX, y: item.minY)
            rangeModel.endPoint = CGPoint(x: item.maxX, y: item.minY)
            linePoints.append(rangeModel)
        }
        
        return linePoints
    }
    
    
    
}
